<?php
/***********************************************************
 * 字段管理
 * @作者 pcfcms <1131680521@qq.com>
 * @主页 http://www.pcfcms.com
 * @时间 2021年01月01日
***********************************************************/
namespace app\admin\controller;
use think\facade\Db;
use think\facade\Cache;
use think\facade\Request;
use app\admin\model\Channelfield as ChannelfieldModel;
use app\admin\model\FieldType as FieldTypeModel;
class Field extends Base
{
    public $FieldTypeModel;
    public $ChannelfieldModel;
    public $arctype_channel_id;
    public $popedom;
    public function _initialize() {
        parent::_initialize();
        $this->FieldTypeModel = new FieldTypeModel(); 
        $this->ChannelfieldModel = new ChannelfieldModel();
        $this->arctype_channel_id = config('pcfcms.arctype_channel_id');//等于-99是系统默认参数
        $ctl_act = strtolower('type/index');
        $this->popedom = appfile_popedom($ctl_act);
    }

    // 字段管理
    public function channel_index()
    {
        if(!$this->popedom["list"]){
            return $this->Notice(config('params.auth_msg.list'),true,3,false);
        }
        //获取到所有GET参数
        $post = input('param.');

        //同步栏目绑定的自定义字段
        //$this->syn_channelfield_bind();
        $channel_id = input('param.channel_id/d');

        //同步更新附加表字段到自定义模型字段表中
        if (isset($post['searchopt'])) {
            $this->FieldTypeModel->ChannelTable($channel_id);
        }

        if (Request::isAjax()) {
            $post = input('param.');
            return $this->ChannelfieldModel->tableData($post);
        }

        $this->assign('channel_id', $channel_id);
        return $this->fetch();
    }

    // 新增
    public function channel_add()
    {
        $channel_id  = [];
        $result = ['status' => false,'msg' => '失败','url'=>''];
        $channel_id = input('param.channel_id/d', 0);
        if (empty($channel_id)) {
            $result = ['status' => false,'msg' => '参数有误！'];
            return $result;
        }
        if (Request::isAjax()) {
            //验证权限
            if(!$this->popedom["add"]){
                if(config('params.auth_msg.test')){
                    $result = ['status' => false, 'msg' => config('params.auth_msg.pcfcms')];
                    return $result;
                }else{
                    $result = ['status' => false, 'msg' => config('params.auth_msg.add')];
                    return $result;                    
                }
            }
            $post = input('param.');
            // 判断是否存在|杠
            $IsData = strstr($post['dfvalue'], '|');
            if (!empty($IsData)) {
                $result = ['status' => false,'msg' => '不可输入 | 杠'];
                return $result;
            }
            if (empty($post['dtype']) || empty($post['title']) || empty($post['name'])) {
                $result = ['status' => false,'msg' => '缺少必填信息！'];
                return $result;
            }
            if (1 == preg_match('/^([_]+|[0-9]+)$/', $post['name'])) {
                $result = ['status' => false,'msg' => '字段名称格式不正确！'];
                return $result;
            }else if (preg_match('/^type/', $post['name'])) {
                $result = ['status' => false,'msg' => '模型字段名称不允许以type开头！'];
                return $result;
            }
            // 去除中文逗号，过滤左右空格与空值、以及单双引号
            $dfvalue = str_replace('，', ',', $post['dfvalue']);
            $dfvalue = func_preg_replace(['"','\'',';'], '', $dfvalue);
            $dfvalueArr = explode(',', $dfvalue);
            foreach ($dfvalueArr as $key => $val) {
                $tmp_val = trim($val);
                if ('' == $tmp_val) {unset($dfvalueArr[$key]);continue;}
                $dfvalueArr[$key] = trim($val);
            }
            $dfvalue = implode(',', $dfvalueArr);
            //默认值必填字段
            $fieldtype_list = Db::name('field_type')->column('name,title,ifoption','name');
            if (isset($fieldtype_list[$post['dtype']]) && 1 == $fieldtype_list[$post['dtype']]['ifoption']) {
                if (empty($dfvalue)) {
                    $result = ['status' => false,'msg' => "你设定了字段为【".$fieldtype_list[$post['dtype']]['title']."】类型，默认值不能为空！"];
                    return $result;
                }
            }
            //当前模型对应的数据表
            $table_name = Db::name('channel_type')->where('id',$channel_id)->value('table');
            $table = config('database.connections.mysql.prefix').$table_name.'_content';
            //检测字段是否存在于主表与附加表中
            if (true == $this->FieldTypeModel->checkChannelFieldList($table, $post['name'], $channel_id)) {
                $result = ['status' => false,'msg' => "字段名称 ".$post['name']." 与系统字段冲突！"];
                return $result;
            }
            if (empty($post['typeids'])) {
                $result = ['status' => false,'msg' => '请选择指定栏目！'];
                return $result;
            }
            //组装完整的SQL语句，并执行新增字段
            $fieldinfos = $this->FieldTypeModel->GetFieldMake($post['dtype'], $post['name'], $dfvalue, $post['title']);
            $ntabsql = $fieldinfos[0];
            $buideType = $fieldinfos[1];
            $maxlength = $fieldinfos[2];
            $sql = " ALTER TABLE `$table` ADD  $ntabsql ";
            if (false !== Db::execute($sql)) {
                //保存新增字段的记录
                $newData = array(
                    'dfvalue'   => $dfvalue,
                    'maxlength' => $maxlength,
                    'define'  => $buideType,
                    'ifcontrol' => 0,
                    'sort_order' => 100,
                    'add_time' => getTime(),
                    'update_time' => getTime()
                );
                $data = array_merge($post, $newData);
                unset($data['typeids']);
                Db::name('channelfield')->save($data);
                $field_id = Db::name('channelfield')->getLastInsID();
                //保存栏目与字段绑定的记录
                $typeids = $post['typeids'];
                if (!empty($typeids)) {
                    $addData = [];
                    foreach ($typeids as $key => $val) {
                        if (1 < count($typeids) && empty($val)) {continue;}
                        $addData[] = [
                            'typeid'        => $val,
                            'field_id'      => $field_id,
                            'add_time'      => getTime(),
                            'update_time'   => getTime(),
                        ];
                    }
                    if(!empty($addData)){
                        foreach ($addData as $key => $value) {
                            Db::name('channelfield_bind')->save($value);
                        }
                    }
                }
                //重新生成数据表字段缓存文件
                try {
                    schemaTable($table);
                } catch (\Exception $e) {}
                $result = ['status' => true,'msg' => '操作成功','url'=>Request::baseFile().'/field/channel_index?channel_id='.$channel_id];
                return $result;
            }
        }
        //字段类型列表
        $assign_data['fieldtype_list'] = Db::name('field_type')->field('name,title,ifoption')->order('sort_order asc')->select()->toArray();
        //允许发布文档列表的栏目
        $select_html = allow_release_arctype(0, [$channel_id],true,true);
        $this->assign('select_html',$select_html);
        //模型ID
        $assign_data['channel_id'] = $channel_id;
        $this->assign($assign_data);
        return $this->fetch();
    }

    // 编辑
    public function channel_edit()
    {
        $channel_id = input('param.channel_id/d', 0);
        if (empty($channel_id)) {
            $result = ['status' => false, 'msg' => "参数有误！"];
            return $result; 
        }

        if (Request::isAjax()) {
            if(!$this->popedom["modify"]){
                if(config('params.auth_msg.test')){
                    $result = ['status' => false, 'msg' => config('params.auth_msg.pcfcms')];
                    return $result;
                }else{
                    $result = ['status' => false, 'msg' => config('params.auth_msg.modify')];
                    return $result;                    
                }
            } 
            $post = input('post.', '', 'trim');
            if (empty($post['dtype']) || empty($post['title']) || empty($post['name'])) {
                $result = ['status' => false, 'msg' => "缺少必填信息！"];
                return $result;
            }
            if (1 == preg_match('/^([_]+|[0-9]+)$/', $post['name'])) {
                $result = ['status' => false, 'msg' => "字段名称格式不正确！"];
                return $result;
            } else if (preg_match('/^type/', $post['name'])) {
                $result = ['status' => false, 'msg' => "模型字段名称不允许以type开头！"];
                return $result;
            }
            $info = Db::name('channelfield')->where('id',$post['id'])->field('ifsystem,ifcontrol,ifmain')->find();
            if (!empty($info['ifcontrol'])) {
                $result = ['status' => false, 'msg' => "系统字段不允许更改！"];
                return $result;
            }
            if (!empty($info['ifsystem']) && ($post['old_name'] != $post['name'] || $post['old_dtype'] != $post['dtype'])){
                $result = ['status' => false, 'msg' => "系统字段不允许更改字段名称和字段类型！"];
                return $result;
            }
            $old_name = $post['old_name'];
            // 去除中文逗号，过滤左右空格与空值
            $dfvalue = str_replace('，', ',', $post['dfvalue']);
            $dfvalue = func_preg_replace(['"','\'',';'], '', $dfvalue);
            $dfvalueArr = explode(',', $dfvalue);
            foreach ($dfvalueArr as $key => $val) {
                $tmp_val = trim($val);
                if ('' == $tmp_val) {
                    unset($dfvalueArr[$key]);
                    continue;
                }
                $dfvalueArr[$key] = trim($val);
            }
            $dfvalue = implode(',', $dfvalueArr);
            // 默认值必填字段
            $fieldtype_list = Db::name('field_type')->column('name,title,ifoption','name');
            if (isset($fieldtype_list[$post['dtype']]) && 1 == $fieldtype_list[$post['dtype']]['ifoption']) {
                if (empty($dfvalue)) {
                    $result = ['status' => false, 'msg' => "你设定了字段为【".$fieldtype_list[$post['dtype']]['title']."】类型，默认值不能为空！ "];
                    return $result;
                }
            }
            // 当前模型对应的数据表
            $table_name = Db::name('channel_type')->where('id',$channel_id)->value('table');
            $table = config('database.connections.mysql.prefix').$table_name.'_content';
            // 检测字段是否存在于主表与附加表中
            if (true == $this->FieldTypeModel->checkChannelFieldList($table, $post['name'], $channel_id, array($old_name))) {
                $result = ['status' => false, 'msg' => "字段名称 ".$post['name']." 与系统字段冲突！"];
                return $result;
            }
            if (empty($post['typeids'])) {
                $result = ['status' => false, 'msg' => "请选择指定栏目！"];
                return $result;
            }
            // 组装完整的SQL语句，并执行编辑字段
            $fieldinfos = $this->FieldTypeModel->GetFieldMake($post['dtype'], $post['name'], $dfvalue, $post['title']);
            $ntabsql = $fieldinfos[0];
            $buideType = $fieldinfos[1];
            $maxlength = $fieldinfos[2];
            $new_dfvalue = $fieldinfos[3];
            // 此字段为主表2的字段
            if ($info['ifmain'] == 2){   
                $table = config('database.connections.mysql.prefix').$table_name.'_system';
            }
            $sql = " ALTER TABLE `$table` CHANGE COLUMN `{$old_name}` $ntabsql ";
            if (false !== Db::execute($sql)) {
                //将空数据变更为默认值
                $update_sql = "UPDATE `$table` SET `{$post['name']}` ='$new_dfvalue' WHERE `{$post['name']}`='0' or `{$post['name']}`='' or `{$post['name']}` is NULL;";
                Db::execute($update_sql);
                $newData = array(
                    'dfvalue'   => $dfvalue,
                    'maxlength' => $maxlength,
                    'define'  => $buideType,
                    'update_time' => getTime(),
                );
                $data = array_merge($post, $newData);
                unset($data['old_name'],$data['old_dtype'],$data['typeids']);
                Db::name('channelfield')->where('id',$post['id'])->cache(true,null,"channelfield")->save($data);
                // 保存栏目与字段绑定的记录
                $field_id = $post['id'];
                Db::name('channelfield_bind')->where(['field_id'=>$field_id])->delete();
                $typeids = $post['typeids'];
                if (!empty($typeids)) {
                    $addData = [];
                    foreach ($typeids as $key => $val) {
                        if (1 < count($typeids) && empty($val)) {
                            continue;
                        }
                        $addData[] = [
                            'typeid'        => $val,
                            'field_id'      => $field_id,
                            'add_time'      => getTime(),
                            'update_time'   => getTime()
                        ];
                    }
                    if(!empty($addData)){
                        foreach ($addData as $key => $value) {
                            Db::name('channelfield_bind')->save($value);
                        }
                    }
                }
                // 重新生成数据表字段缓存文件
                try {
                    schemaTable($table);
                } catch (\Exception $e) {}
                Cache::clear('channelfield');
                $result = ['status' => true, 'msg' => "操作成功",'url' => Request::baseFile().'/field/channel_index?channel_id='.$channel_id];
                return $result;
            }else {
                $sql = " ALTER TABLE `$table` ADD  $ntabsql ";
                if (false === Db::execute($sql)) {
                    $result = ['status' => false, 'msg' => "操作失败"];
                    return $result;
                }
            }
        }
        $id = input('param.id/d', 0);
        $info = array();
        if (!empty($channel_id)) {
            $info = Db::name('channelfield')->where('id',$id)->find();
        }
        if (!empty($info['ifcontrol'])) {
            $result = ['status' => false, 'msg' => "不可控制字段不允许更改！"];
            return $result;
        }
        //字段类型列表
        $assign_data['fieldtype_list'] = Db::name('field_type')->field('name,title,ifoption')->order('sort_order asc')->select()->toArray();
        //允许发布文档列表的栏目
        $typeids = Db::name('channelfield_bind')->where('field_id',$id)->column('typeid');
        $select_html = allow_release_arctype($typeids, [$channel_id],true,true);
        $this->assign('select_html',$select_html);
        $this->assign('typeids',$typeids);
        //模型ID
        $assign_data['channel_id'] = $channel_id;
        $assign_data['info'] = $info;
        $this->assign($assign_data);
        return $this->fetch();
    }

    // 删除
    public function channel_del()
    {
        $result = ['status' => false,'msg' => '失败','url' => ''];        
        //验证权限
        if(!$this->popedom["delete"]){
            if(config('params.auth_msg.test')){
                $result = ['status' => false, 'msg' => config('params.auth_msg.pcfcms')];
                return $result;
            }else{
                $result = ['status' => false, 'msg' => config('params.auth_msg.delete')];
                return $result;                    
            }
        }
        $channel_id = input('channel_id/d',0);
        $id = input('param.del_id/d',0);
        if(!empty($id)){
            $row = $this->FieldTypeModel->delChannelField($id);//删除表字段
            if ($row['code'] > 0) {
                $map = [
                    'id' => $id,
                    'channel_id' => $channel_id
                ];
                $result = Db::name('channelfield')->field('channel_id,name')->where($map)->select();
                //删除字段的记录
                Db::name('channelfield')->where($map)->delete();
                //删除栏目与字段绑定的记录
                Db::name('channelfield_bind')->where('field_id',$id)->delete();
                $result = ['status' => true,'msg' => '删除成功'];
                return $result;
            }else{
                $result = ['status' => false,'msg' => $row['msg']];
                return $result;
            }
            //重新生成数据表字段缓存文件
            try {
                schemaTable($table);
            } catch (\Exception $e) {}
            $result = ['status' => false,'msg' => $row['msg']];
            return $result;
        }else{
            $result = ['status' => false,'msg' => '参数有误'];
            return $result;
        }
    }

    // 同步栏目绑定的自定义字段
    private function syn_channelfield_bind()
    {
        $field_ids = Db::name('channelfield')
                    ->where('ifmain','=',0)
                    ->where('channel_id','<>',-99)
                    ->select()->toArray();
        foreach ($field_ids as $key => $value) {
            $field_ids[$key] = $value['id'];
        }
        if (!empty($field_ids)) {
            $totalRow = Db::name('channelfield_bind')->count();
            if (empty($totalRow)) {
                $sveData = [];
                foreach ($field_ids as $key => $val) {
                    $sveData[] = [
                        'typeid'        => 0,
                        'field_id'      => $val,
                        'add_time'      => getTime(),
                        'update_time'   => getTime(),
                    ];
                }
                Db::name('channelfield_bind')->save($sveData);
            }
        }
    }

}